﻿using System.Diagnostics;

namespace EveKillboard.Controllers
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Linq;
    using System.Threading;
    using System.Web.Mvc;
    using System.Web.UI;
    using Content;
    using Core;
    using Core.Interfaces;
    using Core.Services;
    using Core.Views;
    using Data;

    public class KillboardController : LocalizedController
    {
        private const int SHORT_CACHE_DURATION = 30;
        private const int DEFAULT_CACHE_DURATION = 60;
        private const int LONG_CACHE_DURATION = 600;
        private const int MAX_COUNT = 100;

        private readonly IDataAccessProvider _dap = new DataAccessProvider();

        static IEnumerable<KillmailView> GetKills(int count, int skip)
        {
            using (var dap = new DataAccessProvider())
            {
                var corps = dap
                    .FindAll<KillboardParameter>(p => p.Key == KillboardParameter.KEY_CORP, false)
                    .ToArray()
                    .Select(p => int.Parse(p.Value));

                var alliances = dap
                    .FindAll<KillboardParameter>(p => p.Key == KillboardParameter.KEY_ALLIANCE, false)
                    .ToArray()
                    .Select(p => int.Parse(p.Value));

                return dap.FindAll<KillView>(k => k.KillmailValue > 0 && !corps.Contains(k.CorporationId.Value) && !alliances.Contains(k.AllianceId.HasValue ? k.AllianceId.Value : 0), false)
                         .OrderByDescending(k => k.Date)
                         .Skip(skip)
                         .Take(count)
                         .ToArray();    
            }
        }

        static IEnumerable<KillmailView> GetLosses (int count, int skip)
        {
            using (var dap = new DataAccessProvider() )
            {
                var corps = dap
                    .FindAll<KillboardParameter>(p => p.Key == KillboardParameter.KEY_CORP, false)
                    .ToArray()
                    .Select(p => int.Parse(p.Value));

                var alliances = dap
                    .FindAll<KillboardParameter>(p => p.Key == KillboardParameter.KEY_ALLIANCE, false)
                    .ToArray()
                    .Select(p => int.Parse(p.Value));

                return dap.FindAll<LossView>(k => k.KillmailValue > 0 && corps.Contains(k.CorporationId.Value) || alliances.Contains(k.AllianceId.HasValue ? k.AllianceId.Value : 0), false)
                        .OrderByDescending(k => k.Date)
                        .Skip(skip)
                        .Take(count)
                        .ToArray();
            }
        }
        
        public IEveApiServices ApiServices
        {
            get { return EveApiServicesProvider.Instance; }
        }

        public ActionResult Index()
        {
            return RedirectToAction("Kills");
        }

        //[NonAction]
        //public int GetCorporationInternalId(string name)
        //{
        //    if (string.IsNullOrEmpty(name)) return 0;
        //    using( var dap = new DataAccessProvider())
        //    {
        //        var corp = dap.Find<Corporation>(c => c.Name == name);
        //        return corp == null ? 0 : corp.Id;    
        //    }
        //}
        //[NonAction]
        //public int GetAllianceInternalId(string name)
        //{
        //    if (string.IsNullOrEmpty(name)) return 0;
        //    using( var dap = new DataAccessProvider())
        //    {
        //        var ally = dap.Find<Alliance>(a => a.Name == name);
        //        return ally == null ? 0 : ally.Id;    
        //    }
        //}

        public ViewResult Kills()
        {
            ViewData.Add("isKill", true);
            return View("Index");
        }
        
        [HttpPost]
        [OutputCacheAttribute(Duration = DEFAULT_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public PartialViewResult Kills(int index)
        {
            var kills = GetKills(MAX_COUNT, MAX_COUNT * index);

            bool canGoPrevious = index > 0;
            bool canGoNext = kills.Count() == MAX_COUNT;

            ViewData.Add("isKill", true);
            ViewData["onclick"] = null; 
            ViewData["next"] = string.Format("evekillboard.loadKills('{0}',{1})", Url.Action("Kills", "Killboard"), canGoNext ? index + 1 : 0);
            ViewData["previous"] = string.Format("evekillboard.loadKills('{0}',{1})", Url.Action("Kills", "Killboard"), canGoPrevious ? index - 1 : 0);

            return PartialView("KillmailsListPartialView", kills);
        }

        public ViewResult Losses()
        {
            ViewData.Add("isKill", false);
            return View("Index");
        }

        [HttpPost]
        [OutputCacheAttribute(Duration = SHORT_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public PartialViewResult Losses(int index)
        {
            var losses = GetLosses(MAX_COUNT, MAX_COUNT*index);
            bool canGoPrevious = index > 0;
            bool canGoNext = losses.Count() == MAX_COUNT;

            ViewData.Add("isKill", false);
            ViewData["onclick"] = null;
            ViewData["next"] = string.Format("evekillboard.loadKills('{0}',{1})", Url.Action("Losses", "Killboard"), canGoNext ? index + 1 : 0);
            ViewData["previous"] = string.Format("evekillboard.loadKills('{0}',{1})", Url.Action("Losses", "Killboard"), canGoPrevious ? index - 1 : 0);

            return PartialView("KillmailsListPartialView", losses);
        }
        
        [OutputCacheAttribute(Duration = LONG_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public ActionResult Details(int? id)
        {
            if (!id.HasValue) return RedirectToAction("Index", "Killboard");
            //using(var _dap = new DataAccessProvider())
            //{
                var km = _dap.Find<Killmail>(k => k.Id == id.Value);
                if (km == null) return RedirectToAction("Index", "Killboard");
                return View("Details", km);    
            //}
        }

        public ViewResult Post(string error)
        {
            ViewBag.IsInGame = base.IsInGame;
            ViewBag.IsTrusted = base.IsTrusted;

            if (!string.IsNullOrEmpty(error))
                ViewBag.Error = error;

            return View("Post");
        }
        [HttpPost]
        public ActionResult Add(string content)
        {
            if(string.IsNullOrEmpty(content))return new EmptyResult();

            using (var dap = new DataAccessProvider())
                try
                {
                    var worker = new KillmailWorker()
                                        {
                                            ApiServices = this.ApiServices,
                                            DataAccessProvider = dap,
                                            PricesProvider = new EvePriceServicesProvider(),
                                            ItemPriceRefreshDelay = 3,
                                            Trace = new TraceSource("KillmailWorker")
                                        };

                    var km = worker.SaveKillmail(new Core.Parsers.KillmailTextParser().Parse(content));
                        
                    if (km != null)
                    {
                        return new ContentResult() { Content = string.Format(Labels.killmail_saved_link, km.Id), ContentType = "html" };
                    }
                }
                catch (Core.Exceptions.KillmailAlreadyExistsException e)
                {
                    if (e.Killmail != null)
                        return new ContentResult() { Content = string.Format(Labels.killmail_exists_link, e.Killmail.Id), ContentType = "html" };
                }
                catch (Exception exp)
                {
                    return PartialView("ErrorPartialView", exp);
                }

            return new EmptyResult();
        }
        [HttpPost]
        [OutputCacheAttribute(Duration = DEFAULT_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public PartialViewResult TopCharactersKillsMonth(int? year, int? month)
        {
            int currentYear = year.GetValueOrDefault(DateTime.Today.Year);
            int currentMonth = month.GetValueOrDefault(DateTime.Today.Month);
            using (var dap = new DataAccessProvider())
            {
                var chars =
                    dap.FindAll<TopCharacterKillsMonthView>(c => c.Year == currentYear && c.Month == currentMonth, false)
                        .OrderByDescending(k => k.Count)
                        .Take(10)
                        .ToArray();

                var date = new DateTime(currentYear, currentMonth, 1);
                var previous = date.AddMonths(-1);
                var next = date.AddMonths(1);

                ViewData["title"] = string.Format(Thread.CurrentThread.CurrentUICulture, "{0:MMMM yyyy}", date);
                ViewData["onclick_previous"] = string.Format("evekillboard.appendResult('{0}','topCharacterKillsMonthContent',{1})", Url.Action("TopCharactersKillsMonth", "Killboard"), string.Format("{{ year:{0}, month:{1} }}", previous.Year, previous.Month));
                ViewData["onclick_next"] = next > DateTime.Today ? null : string.Format("evekillboard.appendResult('{0}','topCharacterKillsMonthContent',{1})", Url.Action("TopCharactersKillsMonth", "Killboard"), string.Format("{{ year:{0}, month:{1} }}", next.Year, next.Month));
                return PartialView("TopListPartialView", chars);        
            }
            
        }
        [HttpPost]
        [OutputCacheAttribute(Duration = DEFAULT_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public PartialViewResult TopCharactersKillsWeek(int? year, int? month, int? week)
        {
            int currentYear = year.GetValueOrDefault(DateTime.Today.Year);
            int currentMonth = month.GetValueOrDefault(DateTime.Today.Month);
            int currentWeek = week.GetValueOrDefault(CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(DateTime.UtcNow.Date, CultureInfo.InvariantCulture.DateTimeFormat.CalendarWeekRule, CultureInfo.InvariantCulture.DateTimeFormat.FirstDayOfWeek));

            using (var dap = new DataAccessProvider())
            {
                var chars =
                dap.FindAll<TopCharacterKillsWeekView>(c => c.Year == currentYear && c.Month == currentMonth && c.Week == currentWeek, false)
                    .OrderByDescending(k => k.Count)
                    .Take(10)
                    .ToArray();

                var date = new DateTime(currentYear, currentMonth, 1);

                while (CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(date, CultureInfo.InvariantCulture.DateTimeFormat.CalendarWeekRule, CultureInfo.InvariantCulture.DateTimeFormat.FirstDayOfWeek) != currentWeek)
                {
                    date = CultureInfo.InvariantCulture.Calendar.AddWeeks(date, 1);
                }

                var previous = CultureInfo.InvariantCulture.Calendar.AddWeeks(date, -1);
                var next = CultureInfo.InvariantCulture.Calendar.AddWeeks(date, 1);

                ViewData["title"] = string.Format(Thread.CurrentThread.CurrentUICulture, "{0:MMMM yyyy} {1} {2}", date, Labels.week, currentWeek);
                ViewData["onclick_previous"] = string.Format("evekillboard.appendResult('{0}','topCharacterKillsWeekContent',{1})", Url.Action("TopCharactersKillsWeek", "Killboard"), string.Format("{{year:{0},month:{1},week:{2}}}", previous.Year, previous.Month, CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(previous, CultureInfo.InvariantCulture.DateTimeFormat.CalendarWeekRule, CultureInfo.InvariantCulture.DateTimeFormat.FirstDayOfWeek)));
                ViewData["onclick_next"] = next > DateTime.Today && CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(next, CultureInfo.InvariantCulture.DateTimeFormat.CalendarWeekRule, CultureInfo.InvariantCulture.DateTimeFormat.FirstDayOfWeek) > CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(DateTime.UtcNow, CultureInfo.InvariantCulture.DateTimeFormat.CalendarWeekRule, CultureInfo.InvariantCulture.DateTimeFormat.FirstDayOfWeek)
                    ? null
                    : string.Format("evekillboard.appendResult('{0}','topCharacterKillsWeekContent',{1})", Url.Action("TopCharactersKillsWeek", "Killboard"), string.Format("{{year:{0},month:{1},week:{2}}}", next.Year, next.Month, CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(next, CultureInfo.InvariantCulture.DateTimeFormat.CalendarWeekRule, CultureInfo.InvariantCulture.DateTimeFormat.FirstDayOfWeek)));

                return PartialView("TopListPartialView", chars);
            }
            
        }
        [HttpPost]
        [OutputCacheAttribute(Duration = DEFAULT_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public PartialViewResult TopCharactersKillsValueMonth(int? year, int? month)
        {
            int currentYear = year.GetValueOrDefault(DateTime.Today.Year);
            int currentMonth = month.GetValueOrDefault(DateTime.Today.Month);
            using (var dap = new DataAccessProvider() )
            {
                var chars =
                dap.FindAll<TopCharacterKillsValueMonthView>(c => c.Year == currentYear && c.Month == currentMonth, false)
                    .OrderByDescending(v => v.Value)
                    .Take(10)
                    .ToArray();

                var date = new DateTime(currentYear, currentMonth, 1);
                var previous = date.AddMonths(-1);
                var next = date.AddMonths(1);

                ViewData["title"] = string.Format(Thread.CurrentThread.CurrentUICulture, "{0:MMMM yyyy}", date);
                ViewData["onclick_previous"] = string.Format("evekillboard.appendResult('{0}','topCharacterKillsMonthValueContent',{1})", Url.Action("TopCharactersKillsValueMonth", "Killboard"), string.Format("{{ year:{0}, month:{1} }}", previous.Year, previous.Month));
                ViewData["onclick_next"] = next > DateTime.Today ? null : string.Format("evekillboard.appendResult('{0}','topCharacterKillsMonthValueContent',{1})", Url.Action("TopCharactersKillsValueMonth", "Killboard"), string.Format("{{ year:{0}, month:{1} }}", next.Year, next.Month));

                return PartialView("TopListPartialView", chars);
            }
            
        }
        [HttpPost]
        [OutputCacheAttribute(Duration = DEFAULT_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public PartialViewResult TopCharactersLossesMonth(int? year, int? month)
        {
            int currentYear = year.GetValueOrDefault(DateTime.Today.Year);
            int currentMonth = month.GetValueOrDefault(DateTime.Today.Month);
            using(var dap = new DataAccessProvider())
            {
                var chars =
                dap.FindAll<TopCharacterLossesMonthView>(c => c.Year == currentYear && c.Month == currentMonth, false)
                    .OrderByDescending(v => v.Count)
                    .Take(10)
                    .ToArray();

                var date = new DateTime(currentYear, currentMonth, 1);
                var previous = date.AddMonths(-1);
                var next = date.AddMonths(1);

                ViewData["title"] = string.Format(Thread.CurrentThread.CurrentUICulture, "{0:MMMM yyyy}", date);
                ViewData["onclick_previous"] = string.Format("evekillboard.appendResult('{0}','topCharacterLossesMonthContent',{1})", Url.Action("TopCharactersLossesMonth", "Killboard"), string.Format("{{ year:{0}, month:{1} }}", previous.Year, previous.Month));
                ViewData["onclick_next"] = next > DateTime.Today ? null : string.Format("evekillboard.appendResult('{0}','topCharacterLossesMonthContent',{1})", Url.Action("TopCharactersLossesMonth", "Killboard"), string.Format("{{ year:{0}, month:{1} }}", next.Year, next.Month));


                return PartialView("TopListPartialView", chars);
            }
            
        }
        [HttpPost]
        [OutputCacheAttribute(Duration = DEFAULT_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public PartialViewResult TopCharactersLossesWeek(int? year, int? month, int? week)
        {
            int currentYear = year.GetValueOrDefault(DateTime.Today.Year);
            int currentMonth = month.GetValueOrDefault(DateTime.Today.Month);
            int currentWeek = week.GetValueOrDefault(CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(DateTime.UtcNow.Date, CultureInfo.InvariantCulture.DateTimeFormat.CalendarWeekRule, CultureInfo.InvariantCulture.DateTimeFormat.FirstDayOfWeek));
            using(var dap = new DataAccessProvider())
            {
                var chars =
                dap.FindAll<TopCharactersLossesWeekView>(c => c.Year == currentYear && c.Month == currentMonth && c.Week == currentWeek, false)
                    .OrderByDescending(v => v.Count)
                    .Take(10).ToArray();

                var date = new DateTime(currentYear, currentMonth, 1);

                while (CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(date, CultureInfo.InvariantCulture.DateTimeFormat.CalendarWeekRule, CultureInfo.InvariantCulture.DateTimeFormat.FirstDayOfWeek) != currentWeek)
                {
                    date = CultureInfo.InvariantCulture.Calendar.AddWeeks(date, 1);
                }

                var previous = CultureInfo.InvariantCulture.Calendar.AddWeeks(date, -1);
                var next = CultureInfo.InvariantCulture.Calendar.AddWeeks(date, 1);

                ViewData["title"] = string.Format(Thread.CurrentThread.CurrentUICulture, "{0:MMMM yyyy} {1} {2}", date, Labels.week, currentWeek);
                ViewData["onclick_previous"] = string.Format("evekillboard.appendResult('{0}','topCharacterLossesWeekContent',{1})", Url.Action("TopCharactersLossesWeek", "Killboard"), string.Format("{{year:{0},month:{1},week:{2}}}", previous.Year, previous.Month, CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(previous, CultureInfo.InvariantCulture.DateTimeFormat.CalendarWeekRule, CultureInfo.InvariantCulture.DateTimeFormat.FirstDayOfWeek)));
                ViewData["onclick_next"] = next > DateTime.Today && CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(next, CultureInfo.InvariantCulture.DateTimeFormat.CalendarWeekRule, CultureInfo.InvariantCulture.DateTimeFormat.FirstDayOfWeek) > CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(DateTime.UtcNow, CultureInfo.InvariantCulture.DateTimeFormat.CalendarWeekRule, CultureInfo.InvariantCulture.DateTimeFormat.FirstDayOfWeek) ? null : string.Format("evekillboard.appendResult('{0}','topCharacterLossesWeekContent',{1})", Url.Action("TopCharactersLossesWeek", "Killboard"), string.Format("{{year:{0},month:{1},week:{2}}}", next.Year, next.Month, CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(next, CultureInfo.InvariantCulture.DateTimeFormat.CalendarWeekRule, CultureInfo.InvariantCulture.DateTimeFormat.FirstDayOfWeek)));

                return PartialView("TopListPartialView", chars);
            }
            
        }
        [HttpPost]
        [OutputCacheAttribute(Duration = DEFAULT_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public PartialViewResult TopCorporationsKillsMonth(int? year, int? month)
        {
            int currentYear = year.GetValueOrDefault(DateTime.Today.Year);
            int currentMonth = month.GetValueOrDefault(DateTime.Today.Month);
            
            TopCorporationsKillsMonthView[] corps = null;
            using (var dap = new DataAccessProvider())     
                corps = dap.FindAll<TopCorporationsKillsMonthView>(c => c.Year == currentYear && c.Month == currentMonth, false)
                        .OrderByDescending(v => v.Count)
                        .Take(10)
                        .ToArray();

            var date = new DateTime(currentYear, currentMonth, 1);
            var previous = date.AddMonths(-1);
            var next = date.AddMonths(1);

            ViewData["title"] = string.Format(Thread.CurrentThread.CurrentUICulture, "{0:MMMM yyyy}", date);
            ViewData["onclick_previous"] = string.Format("evekillboard.appendResult('{0}','topCorporationsKillsMonthContent',{1})", Url.Action("TopCorporationsKillsMonth", "Killboard"), string.Format("{{ year:{0}, month:{1} }}", previous.Year, previous.Month));
            ViewData["onclick_next"] = next > DateTime.Today ? null : string.Format("evekillboard.appendResult('{0}','topCorporationsKillsMonthContent',{1})", Url.Action("TopCorporationsKillsMonth", "Killboard"), string.Format("{{ year:{0}, month:{1} }}", next.Year, next.Month));

            return PartialView("TopListPartialView", corps);
            
        }
        [HttpPost]
        [OutputCacheAttribute(Duration = DEFAULT_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public PartialViewResult TopCorporationsKillsWeek(int? year, int? month, int? week)
        {
            int currentYear = year.GetValueOrDefault(DateTime.Today.Year);
            int currentMonth = month.GetValueOrDefault(DateTime.Today.Month);
            int currentWeek = week.GetValueOrDefault(CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(DateTime.UtcNow.Date, CultureInfo.InvariantCulture.DateTimeFormat.CalendarWeekRule, CultureInfo.InvariantCulture.DateTimeFormat.FirstDayOfWeek));
            
            TopCorporationsKillsWeekView[] corps = null;
            using (var dap = new DataAccessProvider())
                corps = dap.FindAll<TopCorporationsKillsWeekView>(c => c.Year == currentYear && c.Month == currentMonth && c.Week == currentWeek, false)
                        .OrderByDescending(v => v.Count)
                        .Take(10)
                        .ToArray();

            var date = new DateTime(currentYear, currentMonth, 1);

            while (CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(date, CultureInfo.InvariantCulture.DateTimeFormat.CalendarWeekRule, CultureInfo.InvariantCulture.DateTimeFormat.FirstDayOfWeek) != currentWeek)
            {
                date = CultureInfo.InvariantCulture.Calendar.AddWeeks(date, 1);
            }

            var previous = CultureInfo.InvariantCulture.Calendar.AddWeeks(date, -1);
            var next = CultureInfo.InvariantCulture.Calendar.AddWeeks(date, 1);

            ViewData["title"] = string.Format(Thread.CurrentThread.CurrentUICulture, "{0:MMMM yyyy} {1} {2}", date, Labels.week, currentWeek);
            ViewData["onclick_previous"] = string.Format("evekillboard.appendResult('{0}','topCorporationsKillsWeekContent',{1})", Url.Action("TopCorporationsKillsWeek", "Killboard"), string.Format("{{year:{0},month:{1},week:{2}}}", previous.Year, previous.Month, CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(previous, CultureInfo.InvariantCulture.DateTimeFormat.CalendarWeekRule, CultureInfo.InvariantCulture.DateTimeFormat.FirstDayOfWeek)));
            ViewData["onclick_next"] = next > DateTime.Today && CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(next, CultureInfo.InvariantCulture.DateTimeFormat.CalendarWeekRule, CultureInfo.InvariantCulture.DateTimeFormat.FirstDayOfWeek) > CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(DateTime.UtcNow, CultureInfo.InvariantCulture.DateTimeFormat.CalendarWeekRule, CultureInfo.InvariantCulture.DateTimeFormat.FirstDayOfWeek) ? null : string.Format("evekillboard.appendResult('{0}','topCorporationsKillsWeekContent',{1})", Url.Action("TopCorporationsKillsWeek", "Killboard"), string.Format("{{year:{0},month:{1},week:{2}}}", next.Year, next.Month, CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(next, CultureInfo.InvariantCulture.DateTimeFormat.CalendarWeekRule, CultureInfo.InvariantCulture.DateTimeFormat.FirstDayOfWeek)));

            return PartialView("TopListPartialView", corps);    
            
        }
        [HttpPost]
        [OutputCacheAttribute(Duration = DEFAULT_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public PartialViewResult TopCorporationsLossesMonth(int? year, int? month)
        {
            int currentYear = year.GetValueOrDefault(DateTime.Today.Year);
            int currentMonth = month.GetValueOrDefault(DateTime.Today.Month);
            TopCorporationsLossesMonthView[] corps = null;
            using (var dap = new DataAccessProvider())
                corps = dap.FindAll<TopCorporationsLossesMonthView>(c => c.Year == currentYear && c.Month == currentMonth, false)
                    .OrderByDescending(v => v.Count)
                    .Take(10)
                    .ToArray();

            var date = new DateTime(currentYear, currentMonth, 1);
            var previous = date.AddMonths(-1);
            var next = date.AddMonths(1);

            ViewData["title"] = string.Format(Thread.CurrentThread.CurrentCulture, "{0:MMMM yyyy}", date);
            ViewData["onclick_previous"] = string.Format("evekillboard.appendResult('{0}','topCorporationLossesMonthContent',{1})", Url.Action("TopCorporationsLossesMonth", "Killboard"), string.Format("{{ year:{0}, month:{1} }}", previous.Year, previous.Month));
            ViewData["onclick_next"] = next > DateTime.Today ? null : string.Format("evekillboard.appendResult('{0}','topCorporationLossesMonthContent',{1})", Url.Action("TopCorporationsLossesMonth", "Killboard"), string.Format("{{ year:{0}, month:{1} }}", next.Year, next.Month));

            return PartialView("TopListPartialView", corps);
        }
        [HttpPost]
        [OutputCacheAttribute(Duration = DEFAULT_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public PartialViewResult TopCorporationsLossesWeek(int? year, int? month, int? week)
        {
            int currentYear = year.GetValueOrDefault(DateTime.Today.Year);
            int currentMonth = month.GetValueOrDefault(DateTime.Today.Month);
            int currentWeek = week.GetValueOrDefault(CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(DateTime.UtcNow.Date, CultureInfo.InvariantCulture.DateTimeFormat.CalendarWeekRule, CultureInfo.InvariantCulture.DateTimeFormat.FirstDayOfWeek));
            
            TopCorporationsLossesWeekView[] corps = null;
            using (var dap = new DataAccessProvider())    
                corps = dap.FindAll<TopCorporationsLossesWeekView>(c => c.Year == currentYear && c.Month == currentMonth && c.Week == currentWeek, false)
                    .OrderByDescending(v => v.Count)
                    .Take(10)
                    .ToArray();

            var date = new DateTime(currentYear, currentMonth, 1);

            while (CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(date, CultureInfo.InvariantCulture.DateTimeFormat.CalendarWeekRule, CultureInfo.InvariantCulture.DateTimeFormat.FirstDayOfWeek) != currentWeek)
            {
                date = CultureInfo.InvariantCulture.Calendar.AddWeeks(date, 1);
            }

            var previous = CultureInfo.InvariantCulture.Calendar.AddWeeks(date, -1);
            var next = CultureInfo.InvariantCulture.Calendar.AddWeeks(date, 1);

            ViewData["title"] = string.Format(Thread.CurrentThread.CurrentUICulture, "{0:MMMM yyyy} {1} {2}", date, Labels.week, currentWeek);
            ViewData["onclick_previous"] = string.Format("evekillboard.appendResult('{0}','topCorporationLossesWeekContent',{1})", Url.Action("TopCorporationsLossesWeek", "Killboard"), string.Format("{{year:{0},month:{1},week:{2}}}", previous.Year, previous.Month, CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(previous, CultureInfo.InvariantCulture.DateTimeFormat.CalendarWeekRule, CultureInfo.InvariantCulture.DateTimeFormat.FirstDayOfWeek)));
            ViewData["onclick_next"] = next > DateTime.Today && CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(next, CultureInfo.InvariantCulture.DateTimeFormat.CalendarWeekRule, CultureInfo.InvariantCulture.DateTimeFormat.FirstDayOfWeek) > CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(DateTime.UtcNow, CultureInfo.InvariantCulture.DateTimeFormat.CalendarWeekRule, CultureInfo.InvariantCulture.DateTimeFormat.FirstDayOfWeek)
                ? null
                : string.Format("evekillboard.appendResult('{0}','topCorporationLossesWeekContent',{1})", Url.Action("TopCorporationsLossesWeek", "Killboard"), string.Format("{{year:{0},month:{1},week:{2}}}", next.Year, next.Month, CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(next, CultureInfo.InvariantCulture.DateTimeFormat.CalendarWeekRule, CultureInfo.InvariantCulture.DateTimeFormat.FirstDayOfWeek)));

            return PartialView("TopListPartialView", corps);
            
        }
        [HttpPost]
        [OutputCacheAttribute(Duration = DEFAULT_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public PartialViewResult TopMonthRegionsKill(int? year, int? month)
        {
            TopRegionMonth[] regions = null;
            using (var dap = new DataAccessProvider())
                regions = dap.FindAll<TopRegionMonth>(false).ToArray();
            return PartialView("TopRegionKillsPartialView", regions);
        }
        [HttpPost]
        [OutputCacheAttribute(Duration = DEFAULT_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public PartialViewResult TopWeekRegionsKills(int? year, int? month, int? week)
        {
            TopRegionWeek[] regions = null;
            using (var dap = new DataAccessProvider())
                regions = dap.FindAll<TopRegionWeek>(false).ToArray();
            return PartialView("TopRegionKillsPartialView", regions);    
        }
        [OutputCacheAttribute(Duration = LONG_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public ActionResult Pilot(int? id, string name)
        {
            if ((!id.HasValue || id == 0) && string.IsNullOrEmpty(name)) return RedirectToAction("Index");
            using(var dap = new DataAccessProvider())
            {
                var stats = id.HasValue
                            ? dap.Find<CharacterStats>(c => c.InternalId == id)
                            : dap.Find<CharacterStats>(c => c.Name == name);
                if (stats == null) return RedirectToAction("Index");

                var character = dap.Find<Character>(c => c.Id == stats.InternalId);
                if (character.LastKnownCorporation == null || !character.Updated.HasValue || DateTime.UtcNow.Subtract(character.Updated.Value).Days > 7)
                {
                    var charInfos = ApiServices.GetCharacterInfos(stats.EveId);
                    if (charInfos != null && charInfos.CorporationId > 0)
                    {
                        Corporation corp = null;
                        if (dap.Exists<Corporation>(c => c.Name == charInfos.CorporationName, out corp))
                        {
                            character.LastKnownCorporation = corp;
                            character.Updated = DateTime.UtcNow;

                            if (charInfos.AllianceId > 0 && (corp.LastKnownAlliance == null || !corp.Updated.HasValue || DateTime.UtcNow.Subtract(corp.Updated.Value).Days > 7))
                            {
                                var alliance = dap.Find<Alliance>(a => a.Name == charInfos.AllianceName);
                                corp.LastKnownAlliance = alliance ?? new Alliance() { EveId = charInfos.AllianceId, Name = charInfos.AllianceName, Updated = DateTime.UtcNow };
                                corp.Updated = DateTime.UtcNow;
                            }
                            dap.Save(character);
                        }
                        else
                        {
                            corp = new Corporation()
                            {
                                EveId = charInfos.CorporationId,
                                Name = charInfos.CorporationName,
                                Updated = DateTime.UtcNow
                            };

                            if (charInfos.AllianceId > 0)
                            {
                                var alliance = dap.Find<Alliance>(a => a.Name == charInfos.AllianceName);
                                corp.LastKnownAlliance = alliance ?? new Alliance() { EveId = charInfos.AllianceId, Name = charInfos.AllianceName, Updated = DateTime.UtcNow };
                                corp.Updated = DateTime.UtcNow;
                            }
                            character.LastKnownCorporation = corp;
                            character.Updated = DateTime.UtcNow;
                            dap.Save(character);
                        }
                    }

                }
                ViewData["charInfos"] = new CharacterInfos() { CorporationName = character.LastKnownCorporation == null ? null : character.LastKnownCorporation.Name };
                ViewData["charCorpInternalId"] = character.LastKnownCorporation == null ? 0 : character.LastKnownCorporation.Id;
                return View("StatsView", stats);
            }
            

        }
        [OutputCacheAttribute(Duration = LONG_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public ActionResult Corporation(int? id, string name)
        {
            if ((!id.HasValue || id == 0 ) && string.IsNullOrEmpty(name)) return RedirectToAction("Index");
            using(var dap = new DataAccessProvider())
            {
                var stats = id.HasValue
                            ? dap.Find<CorporationStats>(c => c.InternalId == id)
                            : dap.Find<CorporationStats>(c => c.Name == name);
                if (stats == null) return RedirectToAction("Index");

                var corp = dap.Find<Corporation>(c => c.Id == stats.InternalId);
                if (corp != null && (corp.LastKnownAlliance == null || !corp.Updated.HasValue || DateTime.UtcNow.Subtract(corp.Updated.Value).Days > 7))
                {
                    var corpInfos = ApiServices.GetCorporationInfos(stats.EveId);
                    if (corpInfos != null && corpInfos.AllianceId > 0)
                    {
                        var alliance = dap.Find<Alliance>(a => a.Name == corpInfos.AllianceName);
                        corp.LastKnownAlliance = alliance ?? new Alliance() { EveId = corpInfos.AllianceId, Name = corpInfos.AllianceName, Updated = DateTime.UtcNow };
                        dap.Save(corp);
                    }
                }

                ViewData["corpInfos"] = corp == null || corp.LastKnownAlliance == null ? null : new CorporationInfos() { AllianceName = corp.LastKnownAlliance.Name };
                ViewData["corpAllyInternalId"] = corp == null ? 0 : corp.LastKnownAlliance == null ? 0 : corp.LastKnownAlliance.Id;
                return View("StatsView", stats);
            }
            

        }
        [OutputCacheAttribute(Duration = LONG_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public ActionResult Alliance(int? id, string name)
        {
            if ((!id.HasValue || id == 0) && string.IsNullOrEmpty(name)) return RedirectToAction("Index");
            
            AllianceStats stats = null;
            using (var dap = new DataAccessProvider())
                stats = id.HasValue
                                ? dap.Find<AllianceStats>(c => c.InternalId == id)
                                : dap.Find<AllianceStats>(c => c.Name == name);
             
            if (stats == null) return RedirectToAction("Index");
            return View("StatsView", stats);
        }
        [OutputCacheAttribute(Duration = LONG_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public ActionResult Region(int? id)
        {
            if (!id.HasValue || id == 0) return RedirectToAction("Index");
            return RedirectToAction("Index");
        }
        [HttpPost]
        [OutputCacheAttribute(Duration = LONG_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public JsonResult KillmailItems(int? id)
        {
            if (!id.HasValue) return new JsonResult();

            using(var dap = new DataAccessProvider())
            {
                var km = dap.Find<Killmail>(k => k.Id == id);
                if (km == null) return new JsonResult();

                var slots = dap.Find<ShipSlot>(s => s.ItemId == km.Destroyed.Id);

                var result = new List<object> { new { id = km.Destroyed.Id } };

                if (km.Destroyed.Group.Id == 963) // Tech3 ships
                {
                    result.Add(new
                    {
                        high = (short)km.ItemsFittedHighSlot.Sum(i => i.Quantity),
                        med = (short)km.ItemsFittedMedSlot.Sum(i => i.Quantity),
                        low = (short)km.ItemsFittedLowSlot.Sum(i => i.Quantity),
                        rig = (short)slots.RigSlots,
                        sub = (short)slots.SubSystems
                    });
                }
                else
                    result.Add(slots != null
                                   ? new
                                   {
                                       high = slots.HighSlots,
                                       med = slots.MedSlots,
                                       low = slots.LowSlots,
                                       rig = slots.RigSlots,
                                       sub = slots.SubSystems
                                   }
                                   : new
                                   {
                                       high = (short)0,
                                       med = (short)0,
                                       low = (short)0,
                                       rig = (short)0,
                                       sub = (short)0
                                   });

                int index = 0;
                foreach (var item in km.ItemsFittedHighSlot.OrderBy(i => i.ItemId))
                    for (var q = 0; q < item.Quantity; q++)
                    {
                        index++;
                        result.Add(
                            new
                            {
                                name = string.Format("high{0}", index),
                                id = item.Id,
                                slot = "high",
                                img = string.Format("http://image.eveonline.com/Type/{0}_32.png", item.Item.Id),
                                itemName = item.Item.Name
                            });
                    }

                index = 0;
                foreach (var item in km.ItemsFittedMedSlot.OrderBy(i => i.ItemId))
                    for (var q = 0; q < item.Quantity; q++)
                    {
                        index++;
                        result.Add(
                            new
                            {
                                name = string.Format("med{0}", index),
                                id = item.Id,
                                slot = "med",
                                img = string.Format("http://image.eveonline.com/Type/{0}_32.png", item.Item.Id),
                                itemName = item.Item.Name
                            });
                    }

                index = 0;
                foreach (var item in km.ItemsFittedLowSlot.OrderBy(i => i.ItemId))
                    for (var q = 0; q < item.Quantity; q++)
                    {
                        index++;
                        result.Add(
                            new
                            {
                                name = string.Format("low{0}", index),
                                id = item.Id,
                                slot = "low",
                                img = string.Format("http://image.eveonline.com/Type/{0}_32.png", item.Item.Id),
                                itemName = item.Item.Name
                            });
                    }

                index = 0;
                foreach (var item in km.ItemsFittedRigSlot.OrderBy(i => i.ItemId))
                    for (var q = 0; q < item.Quantity; q++)
                    {
                        index++;
                        result.Add(
                            new
                            {
                                name = string.Format("rig{0}", index),
                                id = item.Id,
                                slot = "rig",
                                img = string.Format("http://image.eveonline.com/Type/{0}_32.png", item.Item.Id),
                                itemName = item.Item.Name
                            });
                    }

                index = 0;
                foreach (var item in km.ItemsFittedSubSlot.OrderBy(i => i.ItemId))
                    for (var q = 0; q < item.Quantity; q++)
                    {
                        index++;
                        result.Add(
                            new
                            {
                                name = string.Format("sub{0}", index),
                                id = item.Id,
                                slot = "sub",
                                img = string.Format("http://image.eveonline.com/Type/{0}_32.png", item.Item.Id),
                                itemName = item.Item.Name
                            });
                    }



                return Json(result.ToArray());
            }
            
        }
        [HttpPost]
        [OutputCacheAttribute(Duration = LONG_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public ContentResult KillmailRaw(int? id)
        {
            var content = new ContentResult();
            if (!id.HasValue) return content;
            using(var dap = new DataAccessProvider())
            {
                var km = dap.Find<Killmail>(k => k.Id == id);
                if (km != null)
                    content.Content = MvcHtmlString.Create(km.ToTextFormat()).ToHtmlString();
                return content;    
            }
            
        }
        [HttpPost]
        [OutputCacheAttribute(Duration = LONG_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public PartialViewResult TopKillsValueView()
        {
            using (var dap = new DataAccessProvider())
            {
                var kills = dap.FindAll<TopKillValue>(false).ToArray();
                return PartialView("TopKillsValuePartialView", kills);    
            }
        }
        [HttpPost]
        [OutputCacheAttribute(Duration = LONG_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public PartialViewResult CorporationCharactersKillsMonth(int? year, int? month, int corp)
        {
            int currentYear = year.GetValueOrDefault(DateTime.Today.Year);
            int currentMonth = month.GetValueOrDefault(DateTime.Today.Month);

            using(var dap = new DataAccessProvider())
            {
                var list =
                dap.FindAll<CorporationCharacterKillsMonthView>(c => c.Year == currentYear && c.Month == currentMonth && c.CorporationInternalId == corp, false)
                    .OrderByDescending(v => v.Count)
                    .Take(10)
                    .ToArray();

                var date = new DateTime(currentYear, currentMonth, 1);
                var previous = date.AddMonths(-1);
                var next = date.AddMonths(1);

                ViewData["title"] = string.Format(Thread.CurrentThread.CurrentUICulture, "{0:MMMM yyyy}", date);
                ViewData["onclick_previous"] = string.Format("evekillboard.loadCorporationCharactersKillsMonth('{0}',{1},{2},{3})", Url.Action("CorporationCharactersKillsMonth", "Killboard"), previous.Year, previous.Month, corp);
                ViewData["onclick_next"] = next > DateTime.Today ? null : string.Format("evekillboard.loadCorporationCharactersKillsMonth('{0}',{1},{2},{3})", Url.Action("CorporationCharactersKillsMonth", "Killboard"), next.Year, next.Month, corp);

                return PartialView("TopListPartialView", list);
            }
            
           
        }
        [HttpPost]
        [OutputCacheAttribute(Duration = LONG_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public PartialViewResult CorporationCharactersLossesMonth(int? year, int? month, int corp)
        {
            int currentYear = year.GetValueOrDefault(DateTime.Today.Year);
            int currentMonth = month.GetValueOrDefault(DateTime.Today.Month);
            using(var dap = new DataAccessProvider())
            {
                var list =
                dap.FindAll<CorporationCharacterLossesMonthView>(c => c.Year == currentYear && c.Month == currentMonth && c.CorporationInternalId == corp, false)
                    .OrderByDescending(v => v.Count)
                    .Take(10)
                    .ToArray();

                var date = new DateTime(currentYear, currentMonth, 1);
                var previous = date.AddMonths(-1);
                var next = date.AddMonths(1);

                ViewData["title"] = string.Format(Thread.CurrentThread.CurrentUICulture, "{0:MMMM yyyy}", date);
                ViewData["onclick_previous"] = string.Format("evekillboard.loadCorporationCharactersLossesMonth('{0}',{1},{2},{3})", Url.Action("CorporationCharactersLossesMonth", "Killboard"), previous.Year, previous.Month, corp);
                ViewData["onclick_next"] = next > DateTime.Today ? null : string.Format("evekillboard.loadCorporationCharactersLossesMonth('{0}',{1},{2},{3})", Url.Action("CorporationCharactersLossesMonth", "Killboard"), next.Year, next.Month, corp);

                return PartialView("TopListPartialView", list);
            }
            
            
        }
        [HttpPost]
        [OutputCacheAttribute(Duration = DEFAULT_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public PartialViewResult CorporationKills(int id, int index = 0)
        {
            CorporationKillView[] kills = null;

            using (var dap = new DataAccessProvider())
                kills = dap.FindAll<CorporationKillView>(c => c.InvolvedCorporationInternalId == id, false)
                    .OrderByDescending(v => v.Date)
                    .Skip(MAX_COUNT / 2 * index)
                    .Take(MAX_COUNT / 2)
                    .ToArray();

            bool canGoNext = kills.Count() == MAX_COUNT / 2;
            bool canGoPrevious = index > 0;

            ViewData["isKill"] = true;
            ViewData["index"] = canGoNext ? index : -1;
            ViewData["onclick"] = string.Format("evekillboard.loadList('{0}',{1},0)", Url.Action("CorporationLosses", "Killboard"), id);
            ViewData["next"] = string.Format("evekillboard.loadList('{0}',{1},{2})", Url.Action("CorporationKills", "Killboard"), id, canGoNext ? index + 1 : 0);
            ViewData["previous"] = string.Format("evekillboard.loadList('{0}',{1},{2})", Url.Action("CorporationKills", "Killboard"), id, canGoPrevious ? index - 1 : 0);
            return PartialView("KillmailsListPartialView", kills);
            
            
        }
        [HttpPost]
        [OutputCacheAttribute(Duration = DEFAULT_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public PartialViewResult CorporationLosses(int id, int index = 0)
        {
            LossView[] losses = null;
            using (var dap = new DataAccessProvider())
                losses = dap.FindAll<LossView>(c => c.CorporationInternalId == id, false)
                        .OrderByDescending(v => v.Date)
                        .Skip(MAX_COUNT / 2 * index)
                        .Take(MAX_COUNT / 2)
                        .ToArray();

            bool canGoNext = losses.Count() == MAX_COUNT / 2;
            bool canGoPrevious = index > 0;

            ViewData["isKill"] = false;
            ViewData["index"] = canGoNext ? index : -1;
            ViewData["onclick"] = string.Format("evekillboard.loadList('{0}',{1},0)", Url.Action("CorporationKills", "Killboard"), id);
            ViewData["next"] = string.Format("evekillboard.loadList('{0}',{1},{2})", Url.Action("CorporationLosses", "Killboard"), id, canGoNext ? index + 1 : 0);
            ViewData["previous"] = string.Format("evekillboard.loadList('{0}',{1},{2})", Url.Action("CorporationLosses", "Killboard"), id, canGoPrevious ? index - 1 : 0);
            return PartialView("KillmailsListPartialView", losses);
            
        }
        [HttpPost]
        [OutputCacheAttribute(Duration = DEFAULT_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public PartialViewResult CharacterKills(int id, int index = 0)
        {
            CharacterKillsView[] kills = null;
            using (var dap = new DataAccessProvider())
                kills = dap.FindAll<CharacterKillsView>(k => k.InvolvedCharacterInternalId == id, false)
                    .OrderByDescending(k => k.Date)
                    .Skip(MAX_COUNT / 2 * index)
                    .Take(MAX_COUNT / 2)
                    .ToArray();

            bool canGoNext = kills.Count() == MAX_COUNT / 2;
            bool canGoPrevious = index > 0;

            ViewData["isKill"] = true;
            ViewData["index"] = canGoNext ? index : -1;
            ViewData["onclick"] = string.Format("evekillboard.loadList('{0}',{1},0)", Url.Action("CharacterLosses", "Killboard"), id);
            ViewData["next"] = string.Format("evekillboard.loadList('{0}',{1},{2})", Url.Action("CharacterKills", "Killboard"), id, canGoNext ? index + 1 : 0);
            ViewData["previous"] = string.Format("evekillboard.loadList('{0}',{1},{2})", Url.Action("CharacterKills", "Killboard"), id, canGoPrevious ? index - 1 : 0);
            return PartialView("KillmailsListPartialView", kills);
        }
        [HttpPost]
        [OutputCacheAttribute(Duration = DEFAULT_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public PartialViewResult CharacterLosses (int id, int index = 0 )
        {
            LossView[] losses = null;
            using (var dap = new DataAccessProvider())
                losses = dap.FindAll<LossView>(k => k.CharacterInternalId == id, false)
                    .OrderByDescending(k => k.Date)
                    .Skip(MAX_COUNT / 2 * index)
                    .Take(MAX_COUNT / 2)
                    .ToArray();

            bool canGoNext = losses.Count() == MAX_COUNT / 2;
            bool canGoPrevious = index > 0;

            ViewData["isKill"] = false;
            ViewData["index"] = canGoNext ? index : -1;
            ViewData["onclick"] = string.Format("evekillboard.loadList('{0}',{1},0)", Url.Action("CharacterKills", "Killboard"), id);
            ViewData["next"] = string.Format("evekillboard.loadList('{0}',{1},{2})", Url.Action("CharacterLosses", "Killboard"), id, canGoNext ? index + 1 : 0);
            ViewData["previous"] = string.Format("evekillboard.loadList('{0}',{1},{2})", Url.Action("CharacterLosses", "Killboard"), id, canGoPrevious ? index - 1 : 0);
            return PartialView("KillmailsListPartialView", losses);

        }
        [HttpPost]
        [OutputCacheAttribute(Duration = DEFAULT_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public PartialViewResult AllianceKills(int id, int index = 0)
        {
            AllianceKillView[] kills = null;

            using (var dap = new DataAccessProvider())
            kills = dap.FindAll<AllianceKillView>(a => a.InvolvedAllianceInternalId == id, false)
                .OrderByDescending(k => k.Date)
                .Skip(MAX_COUNT / 2 * index)
                .Take(MAX_COUNT / 2)
                .ToArray();

            bool canGoNext = kills.Count() == MAX_COUNT / 2;
            bool canGoPrevious = index > 0;

            ViewData["isKill"] = true;
            ViewData["index"] = canGoNext ? index : -1;
            ViewData["onclick"] = string.Format("evekillboard.loadList('{0}',{1},0)", Url.Action("AllianceLosses", "Killboard"), id);
            ViewData["next"] = string.Format("evekillboard.loadList('{0}',{1},{2})", Url.Action("AllianceKills", "Killboard"), id, canGoNext ? index + 1 : 0);
            ViewData["previous"] = string.Format("evekillboard.loadList('{0}',{1},{2})", Url.Action("AllianceKills", "Killboard"), id, canGoPrevious ? index - 1 : 0);
            return PartialView("KillmailsListPartialView", kills);
        }
        [HttpPost]
        [OutputCacheAttribute(Duration = DEFAULT_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public PartialViewResult AllianceLosses(int id, int index = 0)
        {
            LossView[] losses = null;
            using (var dap = new DataAccessProvider())
                losses = dap.FindAll<LossView>(a => a.AllianceInternalId == id, false)
                    .OrderByDescending(k => k.Date)
                    .Skip(MAX_COUNT / 2 * index)
                    .Take(MAX_COUNT / 2)
                    .ToArray();

            bool canGoNext = losses.Count() == MAX_COUNT / 2;
            bool canGoPrevious = index > 0;

            ViewData["isKill"] = false;
            ViewData["index"] = canGoNext ? index : -1;
            ViewData["onclick"] = string.Format("evekillboard.loadList('{0}',{1},0)", Url.Action("AllianceKills", "Killboard"), id);
            ViewData["next"] = string.Format("evekillboard.loadList('{0}',{1},{2})", Url.Action("AllianceLosses", "Killboard"), id, canGoNext ? index + 1 : 0);
            ViewData["previous"] = string.Format("evekillboard.loadList('{0}',{1},{2})", Url.Action("AllianceLosses", "Killboard"), id, canGoPrevious ? index - 1 : 0);
            return PartialView("KillmailsListPartialView", losses);
            
        }
        [HttpPost]
        [OutputCacheAttribute(Duration = DEFAULT_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public PartialViewResult TopAllianceCorporationKills(int id, int? year, int? month)
        {
            int currentYear = year.GetValueOrDefault(DateTime.Today.Year);
            int currentMonth = month.GetValueOrDefault(DateTime.Today.Month);
           
            IEnumerable<TopCorporationKillsView> kills = null;
            using (var dap = new DataAccessProvider())
                kills = dap.FindAll<TopCorporationKillsView>(c => c.AllianceInternalId == id && c.Year == currentYear && c.Month == currentMonth, false)
                            .ToArray()
                            .GroupBy(k => new { k.InternalId, k.EveId, k.Name })
                            .Select(k => new TopCorporationKillsView() { InternalId = k.Key.InternalId, Name = k.Key.Name, EveId = k.Key.EveId, Count = k.Sum(v => v.Count) })
                            .OrderByDescending(a => a.Count)
                            .Take(10);

            var date = new DateTime(currentYear, currentMonth, 1);
            var previous = date.AddMonths(-1);
            var next = date.AddMonths(1);

            ViewData["title"] = string.Format(Thread.CurrentThread.CurrentUICulture, "{0:MMMM yyyy}", date);
            ViewData["onclick_previous"] = string.Format("evekillboard.loadAllianceCorpKills('{0}',{1},{2},{3})", Url.Action("TopAllianceCorporationKills", "Killboard"), id, previous.Year, previous.Month);
            ViewData["onclick_next"] = next > DateTime.Today ? null : string.Format("evekillboard.loadAllianceCorpKills('{0}',{1},{2},{3})", Url.Action("TopAllianceCorporationKills", "Killboard"), id, next.Year, next.Month);
            return PartialView("TopListPartialView", kills);
        }

        [HttpPost]
        [OutputCacheAttribute(Duration = DEFAULT_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public PartialViewResult TopAllianceCorporationLosses(int id, int? year, int? month)
        {
            int currentYear = year.GetValueOrDefault(DateTime.Today.Year);
            int currentMonth = month.GetValueOrDefault(DateTime.Today.Month);

            IEnumerable<TopCorporationsLossesView> losses = null;
            using (var dap = new DataAccessProvider())
                losses = dap.FindAll<TopCorporationsLossesView>(c => c.AllianceInternalId == id && c.Year == currentYear && c.Month == currentMonth, false)
                        .ToArray()
                        .GroupBy(k => new { k.InternalId, k.EveId, k.Name })
                        .Select(k => new TopCorporationsLossesView() { InternalId = k.Key.InternalId, Name = k.Key.Name, EveId = k.Key.EveId, Count = k.Sum(v => v.Count) })
                        .OrderByDescending(a => a.Count)
                        .Take(10);

            var date = new DateTime(currentYear, currentMonth, 1);
            var previous = date.AddMonths(-1);
            var next = date.AddMonths(1);

            ViewData["title"] = string.Format(Thread.CurrentThread.CurrentUICulture, "{0:MMMM yyyy}", date);
            ViewData["onclick_previous"] = string.Format("evekillboard.loadAllianceCorpLosses('{0}',{1},{2},{3})", Url.Action("TopAllianceCorporationLosses", "Killboard"), id, previous.Year, previous.Month);
            ViewData["onclick_next"] = next > DateTime.Today ? null : string.Format("evekillboard.loadAllianceCorpLosses('{0}',{1},{2},{3})", Url.Action("TopAllianceCorporationLosses", "Killboard"), id, next.Year, next.Month);

            return PartialView("TopListPartialView", losses);

        }
        [HttpPost]
        [OutputCacheAttribute(Duration = DEFAULT_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public PartialViewResult CharacterShips(int id, int count = 10)
        {
            CharacterShipsView[] list = null;
            using (var dap = new DataAccessProvider())
                list = dap.FindAll<CharacterShipsView>(c => c.InternalId == id, false).OrderByDescending(v => v.Count).Take(count).ToArray();
            
            return PartialView("TopListPartialView", list);
        }
        [HttpPost]
        [OutputCacheAttribute(Duration = DEFAULT_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public PartialViewResult CharacterWeapons(int id, int count = 10 ) 
        {
            CharacterWeaponsView[] list = null;
            using (var dap = new DataAccessProvider()) 
                list = dap.FindAll<CharacterWeaponsView>(c => c.InternalId == id, false).OrderByDescending(v => v.Count).Take(count).ToArray();
            return PartialView("TopListPartialView", list);
        }
        [HttpPost]
        [OutputCacheAttribute(Duration = DEFAULT_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public PartialViewResult CharacterShipGroupsKills(int id, int count = 10)
        {
            CharacterShipGroupsKillsView[] list = null;
            using (var dap = new DataAccessProvider())
                list = dap.FindAll<CharacterShipGroupsKillsView>(c => c.InternalId == id, false).OrderByDescending(v => v.Count).Take(count).ToArray();
            return PartialView("TopListPartialView", list);    
            
        }
        [HttpPost]
        [OutputCacheAttribute(Duration = DEFAULT_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public JsonResult AllianceActivity(int id)
        {
            if (id == 0) return null;

            var minDate = DateTime.UtcNow.Date.AddDays(-6).Date;

            using(var dap = new DataAccessProvider())
            {
                var kills =
                dap.FindAll<AllianceKillView>(k => k.InvolvedAllianceInternalId == id && k.Date > minDate, false)
                    .OrderByDescending(k => k.Date)
                    .ToArray()
                    .GroupBy(k => k.Date.Date)
                    .Select(g => new { day = DateTime.UtcNow.Date.Subtract(g.Key).Days, value = g.Count() })
                    .OrderBy(k => k.day);

                var losses =
                    dap.FindAll<LossView>(l => l.AllianceInternalId == id && l.Date > minDate, false)
                        .OrderByDescending(k => k.Date)
                        .ToArray()
                        .GroupBy(l => l.Date.Date)
                        .Select(g => new { day = DateTime.UtcNow.Date.Subtract(g.Key).Days, value = g.Count() })
                        .OrderBy(l => l.day);

                var maxKills = kills.Any() ? kills.Max(k => k.value) : 1;
                var maxLosses = losses.Any() ? losses.Max(l => l.value) : 1;

                var killarray = new object[7];
                var lossarray = new object[7];

                for (int i = 0; i < killarray.Length; i++)
                {
                    var current = kills.FirstOrDefault(k => k.day == i);
                    killarray[i] = current == null
                        ? new { day = i, value = 0 }
                        : new { day = current.day, value = current.value };
                }

                for (int i = 0; i < lossarray.Length; i++)
                {
                    var current = losses.FirstOrDefault(k => k.day == i);
                    lossarray[i] = current == null
                        ? new { day = i, value = 0 }
                        : new { day = current.day, value = current.value };
                }
                return Json(new { maxKills, maxLosses, kills = killarray, losses = lossarray });
            }

            
        }
        [HttpPost]
        [OutputCacheAttribute(Duration = DEFAULT_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public JsonResult CorporationActivity(int id)
        {
            if (id == 0) return null;

            var minDate = DateTime.UtcNow.Date.AddDays(-8).Date;
            using(var dap  = new DataAccessProvider())
            {
                var kills = dap.FindAll<CorporationKillView>(k => k.InvolvedCorporationInternalId == id && k.Date > minDate, false)
                .OrderByDescending(k => k.Date)
                .ToArray()
                .GroupBy(k => k.Date.Date)
                .Select(g => new { day = DateTime.UtcNow.Date.Subtract(g.Key).Days, value = g.Count() })
                .OrderBy(k => k.day);

                var losses = dap.FindAll<LossView>(l => l.CorporationInternalId == id && l.Date > minDate, false)
                    .OrderByDescending(k => k.Date)
                    .ToArray()
                    .GroupBy(l => l.Date.Date)
                    .Select(g => new { day = DateTime.UtcNow.Date.Subtract(g.Key).Days, value = g.Count() })
                    .OrderBy(l => l.day);

                var maxKills = kills.Any() ? kills.Max(k => k.value) : 1;
                var maxLosses = losses.Any() ? losses.Max(l => l.value) : 1;
                var killarray = new object[7];
                var lossarray = new object[7];

                for (int i = 0; i < killarray.Length; i++)
                {
                    var current = kills.FirstOrDefault(k => k.day == i);
                    killarray[i] = current == null
                        ? new { day = i, value = 0 }
                        : new { day = current.day, value = current.value };
                }

                for (int i = 0; i < lossarray.Length; i++)
                {
                    var current = losses.FirstOrDefault(k => k.day == i);
                    lossarray[i] = current == null
                        ? new { day = i, value = 0 }
                        : new { day = current.day, value = current.value };
                }
                return Json(new { maxKills, maxLosses, kills = killarray, losses = lossarray });
            }
            
        }
        [HttpPost]
        [OutputCacheAttribute(Duration = DEFAULT_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public JsonResult CharacterActivity(int id)
        {
            if (id == 0) return null;

            var minDate = DateTime.UtcNow.Date.AddDays(-8).Date;
            using(var dap = new DataAccessProvider())
            {
                var kills = dap.FindAll<CharacterKillsView>(k => k.InvolvedCharacterInternalId == id && k.Date > minDate, false)
                .OrderByDescending(k => k.Date)
                .ToArray()
                .GroupBy(k => k.Date.Date)
                .Select(g => new { day = DateTime.UtcNow.Date.Subtract(g.Key).Days, value = g.Count() })
                .OrderBy(k => k.day);

                var losses = dap.FindAll<LossView>(l => l.CharacterInternalId == id && l.Date > minDate, false)
                    .OrderByDescending(k => k.Date)
                    .ToArray()
                    .GroupBy(l => l.Date.Date)
                    .Select(g => new { day = DateTime.UtcNow.Date.Subtract(g.Key).Days, value = g.Count() })
                    .OrderBy(l => l.day);

                var maxKills = kills.Any() ? kills.Max(k => k.value) : 1;
                var maxLosses = losses.Any() ? losses.Max(l => l.value) : 1;

                var killarray = new object[7];
                var lossarray = new object[7];

                for (int i = 0; i < killarray.Length; i++)
                {
                    var current = kills.FirstOrDefault(k => k.day == i);
                    killarray[i] = current == null
                        ? new { day = i, value = 0 }
                        : new { day = current.day, value = current.value };
                }

                for (int i = 0; i < lossarray.Length; i++)
                {
                    var current = losses.FirstOrDefault(k => k.day == i);
                    lossarray[i] = current == null
                        ? new { day = i, value = 0 }
                        : new { day = current.day, value = current.value };
                }

                return Json(new { maxKills, maxLosses, kills = killarray, losses = lossarray });
            }
            
        }
        [HttpPost]
        [OutputCacheAttribute(Duration = DEFAULT_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public JsonResult CharacterContribution(int id, int corpId)
        {
            int? charKills = null;
            int? corpKills = null;
            using( var dap = new DataAccessProvider())
            {
                charKills = corpId > 0 ? dap.Sum<CharacterKills>(c => c.EntityInternalId == id && c.CorporationId == corpId, c => c.Kills) : 0;
                corpKills = id > 0 ? dap.Sum<CorporationKills>(c => c.EntityInternalId == corpId, c => c.Kills) : 0;
            }
            return Json(new { charKills = charKills.HasValue ? charKills.Value : 0, corpKills = corpKills.HasValue ? corpKills.Value : 0 });            
        }
        [HttpPost]
        [OutputCacheAttribute(Duration = DEFAULT_CACHE_DURATION, Location = OutputCacheLocation.ServerAndClient)]
        public JsonResult CorporationContribution(int corpId, int allyId)
        {
            int? corpKills = null;
            int? allyKills = null;
            using(var dap = new DataAccessProvider())
            {
                corpKills = corpId > 0 ? dap.Sum<CorporationKills>(c => c.EntityInternalId == corpId && c.AllianceId == allyId, k => k.Kills) : 0;
                allyKills = allyId > 0 ? dap.Sum<AllianceKills>(a => a.EntityInternalId == allyId, k => k.Kills) : 0;
            }
            return Json(new { allyKills = allyKills.HasValue ? allyKills.Value : 0, corpKills = corpKills.HasValue ? corpKills.Value : 0 });
        }
    }
}
